package WebGamble;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.awt.BorderLayout;
import javax.swing.JPanel;

public class PCEggsStatic extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	static String BaseURL = "http://www.pceggs.com/play/pg28Insert.aspx?LID=";
	static Random rand = new Random();

	static private HttpResponse httpResponse;
	static private DefaultHttpClient httpClient = new DefaultHttpClient();

	static public class showImg extends JPanel {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		JLabel jl = null;
		ImageIcon img = null;

		public showImg(InputStream bmpFile) throws IOException {
			img = new ImageIcon(ImageIO.read(bmpFile));
			jl = new JLabel(img);
			this.setLayout(new BorderLayout());
			this.add(jl, BorderLayout.CENTER);
		}
	}

	static public int GCD(int numA, int numB) {
		int gcd = 1;
		for (int k = 1; k <= numA && k <= numB; k++)
			if (numA % k == 0 && numB % k == 0)
				gcd = k;
		return gcd;
	}

	static public double min(double[] valList) {
		double val;
		val = valList[0];
		for (double value : valList) {
			if (value < val)
				val = value;
		}
		return val;
	}

	static public int MinLoc(double[] valList) {
		double val;
		val = valList[0];
		int i = 0, loc = 0;
		for (double value : valList) {
			if (value < val) {
				val = value;
				loc = i;
			}
			i++;
		}
		return loc;
	}

	static public double max(double[] valList) {
		double val;
		val = valList[0];
		for (double value : valList) {
			if (value > val)
				val = value;
		}
		return val;
	}

	static public int sum(int[] valList) {
		int val = 0;
		for (int value : valList)
			val += value;
		return val;
	}

	static public double sum(double[] valList) {
		double val = 0;
		for (double value : valList)
			val += value;
		return val;
	}

	static public double score1(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double count = 0;
		double s = sum(distribution);
		for (int i = 0; i < 28; i++) {
			score[i] = oddsList[i] * distribution[i] - s;
			if (score[i] < 0)
				count += originDist[i];
		}
		return min(score) - count * 2;
	}

//	static public int[] originDist = { 1, 3, 6, 10, 15, 21, 28, 72, 90, 110,
//			126, 138, 146, 150, 150, 146, 138, 126, 110, 90, 72, 28, 21, 15,
//			10, 6, 3, 1 };
	 static public int[] originDist = {1, 3, 6, 10, 15, 21, 28, 36, 45, 56,
	 63, 67, 71, 77, 77, 71, 67, 63, 56, 45, 36, 28, 21, 15, 10, 6, 3, 1};
	static public double total = sum(originDist);

	static public double score2(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double count = 0;
		double s = sum(distribution);
		for (int i = 0; i < 28; i++) {
			score[i] = (oddsList[i] * distribution[i] - s) * originDist[i];
			if (score[i] < 0)
				count += 1;
		}
		return sum(score) / total - count;
	}

	static public double score3(double[] oddsList, int[] distribution) {
		double[] score = new double[28];
		double s = sum(distribution);
		for (int i = 0; i < 28; i++) {
			score[i] = (oddsList[i] * distribution[i] - s) * originDist[i];
		}
		return sum(score) / total;
	}

	static public int[] baseDist = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
			1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 };

	static public int showStatus(double[] oddsList, int[] distribution,
			int idx, boolean showFlag) {
		double[] score = new double[28];
		int s = sum(distribution);
		int count = 0;
		if (showFlag) {
			System.out.println(idx + "th step:");
			for (int i = 0; i < 28; i++) {
				System.out.printf("%d: %03d, ", i, distribution[i]);
			}
			System.out.println();
		}
		for (int i = 0; i < 28; i++) {
			score[i] = oddsList[i] * distribution[i] - s;
			if (score[i] < 0)
				count++;
			if (showFlag)
				System.out.printf("%d: %06f, ", i, score[i]);
		}
		if (showFlag) {
			System.out.println();
			System.out.println("Total negative: " + count);
			System.out.println("Min: " + min(score));
			System.out.println("Max: " + max(score));
			for (int i = 0; i < 28; i++)
				score[i] = score[i] * originDist[i];
			System.out.println("Avg: " + sum(score) / total);
			System.out.println("Num: " + s);
		}
		return count;
	}

	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws ClientProtocolException,
			IOException, InterruptedException {
		HttpGet httpGet;
		httpGet = new HttpGet("http://www.pceggs.com/nologin.aspx");
		httpResponse = httpClient.execute(httpGet);
		String loginHtml = EntityUtils.toString(httpResponse.getEntity(),
				"UTF-8");
		httpGet.releaseConnection();

		httpGet = new HttpGet(
				"http://www.pceggs.com/VerifyCode_Login.aspx?id=0."
						+ Math.abs(rand.nextLong()));
		httpResponse = httpClient.execute(httpGet);
		JFrame pane = new JFrame("Image Pane");
		pane.getContentPane().add(
				new showImg(httpResponse.getEntity().getContent()));
		pane.pack();
		pane.setVisible(true);
		httpGet.releaseConnection();
		System.out.println("Please enter the verify code:");
		String VerifyCode;
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				System.in));
		VerifyCode = reader.readLine();

		Document loginDoc = Jsoup.parse(loginHtml);
		String loginURL = "http://www.pceggs.com/nologin.aspx";
		Elements loginInputs = loginDoc.select("input");
		HttpPost httpPost = new HttpPost(loginURL);
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		for (Element input : loginInputs) {
			if (input.attr("type").compareToIgnoreCase("password") == 0) {
				input.attr("name", "txt_PWD");
				input.val("qazxcdews123321");
			} else if (input.attr("name").compareToIgnoreCase("email") == 0) {
				input.attr("name", "txt_UserName");
				input.val("365064421@qq.com");
			} else if (input.attr("name").compareToIgnoreCase("txt_VerifyCode") == 0) {
				input.val(VerifyCode);
			} else if (input.attr("name").compareToIgnoreCase("FromUrl") == 0) {
				input.val("http://www.pceggs.com/play/pc28.aspx");
			} else if (input.attr("name").compareToIgnoreCase("Login_Submit") == 0) {
				input.attr("name", "Login_Submit.x");
				input.val("32");
				params.add(new BasicNameValuePair(input.attr("name"), input
						.val()));
				System.out.println(input.attr("name") + ": " + input.val());
				input.attr("name", "Login_Submit.y");
				input.val("8");
				params.add(new BasicNameValuePair(input.attr("name"), input
						.val()));
				System.out.println(input.attr("name") + ": " + input.val());
				continue;
			}

			params.add(new BasicNameValuePair(input.attr("name"), input.val()));
			System.out.println(input.attr("name") + ": " + input.val());
		}
		httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
		httpResponse = httpClient.execute(httpPost);
		if (httpResponse.getStatusLine().getStatusCode() == 302) {
			System.out.println("Login success...");
		}
		loginHtml = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
		// System.out.println(loginHtml);
		// httpPost.releaseConnection();
		pane.dispose();

		int originTimes = 1, altTimes = 3;
        int money = 0, prevMoney = 0, times = originTimes;
        int winCount = 0, loseCount = 0;
        int topCount = 0;
        int positive = 0, negative = 0;
        
        Queue<Integer> window = new LinkedList<Integer>();
        int qLen = 6;
        boolean altFlag = false, warnFlag = false, hiddenFlag = false;
        for(int i = 0; i < qLen; i++) {
        	window.offer(0);
        }
        int originCount = 0;
        boolean holdon = false;
        
        int start = 1000;
		int sumCount = 0;
		int num = 24;
		String htm;
		Document doc;
		Elements elem;
		int[] trendency = new int[num + 1];
		for(int numi = 0; numi < num; numi++) {
			sumCount = 0;
			httpGet = new HttpGet("http://www.pceggs.com/play/PG28Trend.aspx?id=" + (start + num - numi));
			httpResponse = httpClient.execute(httpGet);
			htm = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			httpGet.releaseConnection();
			doc = Jsoup.parse(htm);
			elem = doc.select("table tr:eq(4) td:gt(0)");
			int[] currentDist = new int[28];
			for(int i = 0; i < 28; i++) {
				currentDist[i] = Integer.parseInt(elem.get(i).text());
				if(i >= 8 && i <= 19) {
					sumCount = sumCount + currentDist[i];
				}
			}
			
			httpGet = new HttpGet("http://www.pceggs.com/play/PG28Trend.aspx?id=" + (num - numi));
			httpResponse = httpClient.execute(httpGet);
			htm = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			httpGet.releaseConnection();
			doc = Jsoup.parse(htm);
			elem = doc.select("table tr:eq(4) td:gt(0)");
			for(int i = 0; i < 28; i++) {
				currentDist[i] = Integer.parseInt(elem.get(i).text());
				if(i >= 8 && i <= 19) {
					sumCount = sumCount - currentDist[i];
				}
			}
			System.out.print(sumCount + " ");
			trendency[numi + 1] = sumCount;
		}
		System.out.println();

		while (true) {
			httpGet = new HttpGet("http://www.pceggs.com/play/pc28.aspx");
			httpResponse = httpClient.execute(httpGet);
			String html = EntityUtils.toString(httpResponse.getEntity(),
					"UTF-8");

			// httpGet.releaseConnection();
			Document document = Jsoup.parse(html);
			Elements elements = document.select("#panel tr:eq(5) td:eq(0)");
			if(elements.size() == 0)
				continue;
			int gambleId = Integer.parseInt(elements.get(0).text());
			elements = document.select("#panel tr:eq(5) td:eq(5) script");
			int lid = Integer
					.parseInt(elements.get(0).html().substring(12, 18));
			String gambleURL = BaseURL + lid;
			int i;
			double[] oddsList = new double[28];
			String odds;
			
			for(i = 0; i < num; i++) {
				trendency[i] = trendency[i+1];
			}
			httpGet = new HttpGet("http://www.pceggs.com/play/PG28Trend.aspx?id=1000");
			httpResponse = httpClient.execute(httpGet);
			html = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			httpGet.releaseConnection();
			document = Jsoup.parse(html);
			elements = document.select("table tr:eq(4) td:gt(0)");
			int[] currentDist = new int[28];
			int sumOrigin = 0, sumCur = 0;
			for(i = 0; i < 28; i++) {
				currentDist[i] = Integer.parseInt(elements.get(i).text());
				if(i >= 8 && i <= 19) {
					sumOrigin = sumOrigin + originDist[i];
					sumCur = sumCur + currentDist[i];
				}
			}
			System.out.println(sumCur + " : " + sumOrigin);
			trendency[num] = sumCur;
			int[] trend = trendency.clone();
			for(i = 0; i <= num; i++) {
				if(i == 0) {
					trend[i] = (int) Math.round((trendency[i] + trendency[i+1]) / 2.0);
				}
				else if(i == num) {
					trend[i] = (int) Math.round((trendency[i] + trendency[i-1]) / 2.0);
				}
				else {
					trend[i] = (int) Math.round((trendency[i-1] + trendency[i] + trendency[i+1]) / 3.0);
				}
				System.out.print(trend[i] + " ");
			}
			System.out.println();
			int lmax = -1;
			for(i = num - 1; i > 0; i--) {
				//for local maximum...
				int j;
				for(j = 1; i + j <= num; j++) {
					if(trend[i+j] <= trend[i+j-1]) {
						continue;
					}
					else {
						break;
					}
				}
				j--;
				int k;
				for(k = 1; i - k >= 0; k++) {
					if(trend[i-k] <= trend[i-k+1]) {
						continue;
					}
					else {
						break;
					}
				}
				k--;
				if(j >= 1 && k >= 1 && trend[i+j] < trend[i] - 1 && trend[i-k] < trend[i] /*|| j >= 2 && k >= 1 && trend[i+j] == trend[i] && trend[i-k] < trend[i] && i+j == num*/) {
					//find a local maximum...
					System.out.println("Local maximum found...");
					lmax = i;
					break;
				}
			}
			int lmin = -1;
			for(i = num - 1; i > 0; i--) {
				//for local minimum...
				int j;
				for(j = 1; i + j <= num; j++) {
					if(trend[i+j] >= trend[i+j-1]) {
						continue;
					}
					else {
						break;
					}
				}
				j--;
				int k;
				for(k = 1; i - k >= 0; k++) {
					if(trend[i-k] >= trend[i-k+1]) {
						continue;
					}
					else {
						break;
					}
				}
				k--;
				if(j >= 1 && k >= 1 && trend[i+j] > trend[i] && trend[i-k] > trend[i] || j >= 4 && k >= 1 && trend[i+j] == trend[i] && trend[i-k] > trend[i] && i+j == num) {
					//find a local minimum...
					System.out.println("Local minimum found...");
					lmin = i;
					break;
				}
			}

			httpGet = new HttpGet("http://www.pceggs.com/play/pc28.aspx");
			httpResponse = httpClient.execute(httpGet);
			html = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			httpGet.releaseConnection();
			document = Jsoup.parse(html);
			elements = document.select(".infro span:eq(3)");
			if(elements.text().replaceAll(",", "").isEmpty())
				continue;
			money = Integer.parseInt(elements.text().replaceAll(",", ""));

			System.out.println("Current Money: " + money);
			Pattern p = Pattern.compile("GetRTime\\([0-9]+\\);"), p1 = Pattern
					.compile("[0-9]+");
			Matcher m = p.matcher(html);
			m.find();
			html = m.group();
			m = p1.matcher(html);
			m.find();
			int timeout = Integer.parseInt(m.group());
			if (timeout <= 2) {
				System.out.println("Timeout...");
				Thread.sleep(5000);
				continue;
			}
			
			elements = document.select("#panel tr:gt(5) script");
			if(elements.size() == 0) {
				continue;
			}
			int[] history = new int[10];
			for (i = 0; i < history.length; i++) {
				history[i] = Integer.parseInt(elements.get(i * 4).html()
						.substring(26, 28)) - 10;
				System.out.print(history[i] + ", ");
			}
			System.out.println();
			if(holdon == true) {
				times = originTimes * altTimes;
			}
			
			winCount = 0;
			for (int val : history) {
				if (val >= 8 && val <= 19) {
					winCount++;
				}
			}
			
			winCount = 0;
			for (int val : history) {
				if (val >= 8 && val <= 19) {
					winCount++;
				} else {
					break;
				}
			}
			
			i = 0;
			loseCount = 0;
			times = originTimes;
			for (int val : history) {
				if (val >= 8 && val <= 19) {
					break;
				} else {
					loseCount++;
					times *= altTimes;
				}
				i++;
			}
			
			System.out.println("LoseCount: " + loseCount);
			System.out.println("Current times: " + times);
			prevMoney = money;
			
			System.out.println(lmax + ", " + lmin);
			
			if(hiddenFlag == false && times != originTimes) {
				System.out.println("Normal mode is not interrupted...");
				hiddenFlag = false;
			}
			else {
				if(lmin != -1 && lmin > lmax || lmin == -1 && lmax == -1 && trend[num] > trend[0]) {
					System.out.println("Normal mode...");
					hiddenFlag = false;
				}
				else {
					System.out.println("Hidden mode...");
					hiddenFlag = true;
				}
			}

			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

			long startT = System.currentTimeMillis(), endT;
			httpGet = new HttpGet(
					"http://www.pceggs.com/play/pg28mode.aspx?refresh=" + lid);
			httpGet.addHeader("X_REQUESTED_WITH", "XMLHttpRequest");
			httpGet.addHeader("Referer", gambleURL);
			httpResponse = httpClient.execute(httpGet);
			odds = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			i = 0;
			for (String value : odds.split(",")) {
				oddsList[i] = Double.parseDouble(value);
				System.out.print(oddsList[i] + ", ");
				i++;
			}
			httpGet.releaseConnection();


//          int[] finalDist = {1, 1, 10, 15, 24, 52, 87, 160, 200, 401, 515, 555, 601, 656, 656, 601, 555, 515, 401, 200, 160, 87, 52, 24, 15, 10, 1, 1};
//          int[] finalDist = {1, 3, 4, 7, 16, 32, 47, 123, 154, 290, 373, 402, 435, 475, 475, 435, 402, 373, 290, 154, 123, 47, 32, 16, 7, 4, 3, 1};
//          int[] finalDist = {1, 1, 1, 19, 29, 52, 87, 159, 199, 399, 512, 552, 598, 652, 652, 598, 552, 512, 399, 199, 159, 87, 52, 29, 19, 1, 1, 1};
//          int[] finalDist = {1, 1, 1, 24, 37, 45, 33, 39, 49, 198, 255, 274, 297, 324, 324, 297, 274, 255, 198, 49, 39, 33, 45, 37, 24, 1, 1, 1};
//			int[] finalDist = {1, 1, 1, 4, 8, 10, 16, 39, 49, 160, 205, 220, 239, 260, 260, 239, 220, 205, 160, 49, 39, 16, 10, 8, 4, 1, 1, 1};
			int[] finalDist = {1, 1, 1, 1, 2, 3, 4, 5, 132, 147, 226, 244, 264, 288, 288, 264, 244, 226, 147, 132, 5, 4, 3, 2, 1, 1, 1, 1};
			int[] altFinalDist = {1, 4, 9, 14, 22, 26, 44, 53, 54, 60, 22, 24, 26, 28, 28, 26, 24, 22, 60, 54, 53, 44, 26, 22, 14, 9, 4, 1};

			float randTimes = rand.nextFloat();
			for (i = 0; i < 28; i++) {
				if(warnFlag)
            		finalDist[i] *= (originTimes * randTimes / 2);
				else {
					if(hiddenFlag == true) {
						if (history[0] >= 8 && history[0] <= 19) {
							finalDist[i] = originTimes * altFinalDist[i];
						}
						else {
							finalDist[i] = originTimes * finalDist[i];
						}
					}
					else {
						finalDist[i] *= times;
					}
				}
			}

			httpPost = new HttpPost(
					"http://www.pceggs.com/play/pg28InsertDo.aspx");
			List<NameValuePair> gambleParams = new ArrayList<NameValuePair>();
			String temps = String.valueOf(finalDist[0]);
			int s = finalDist[0];
			for (i = 1; i < 28; i++) {
				temps = temps + "," + finalDist[i];
				gambleParams.add(new BasicNameValuePair("SMONEY", String
						.valueOf(finalDist[i])));
				s += finalDist[i];
			}
			gambleParams.add(new BasicNameValuePair("ALLSMONEY", temps));
			Date date = new Date();
			date.setMinutes((date.getMinutes() / 5 + 1) * 5);
			gambleParams.add(new BasicNameValuePair("CTIME", df.format(date)));
			gambleParams.add(new BasicNameValuePair("Cheat", "CAE"));
			gambleParams
					.add(new BasicNameValuePair("LID", String.valueOf(lid)));
			gambleParams.add(new BasicNameValuePair("SMONEYSUM", String
					.valueOf(s)));
			gambleParams.add(new BasicNameValuePair("SMONEYY", "ALD"));
			gambleParams.add(new BasicNameValuePair("_issue", String
					.valueOf(gambleId)));
			gambleParams.add(new BasicNameValuePair("isdb_p", "0"));
			gambleParams.add(new BasicNameValuePair("lastgain", ""));
			httpPost.setEntity(new UrlEncodedFormEntity(gambleParams,
					HTTP.UTF_8));
			httpPost.addHeader("Host", "www.pceggs.com");
			httpPost.addHeader("Referer", gambleURL);
			httpPost.addHeader("User-Agent",
					"Mozilla/5.0 (Windows NT 6.1; rv:18.0) Gecko/20100101 Firefox/18.0");
			httpResponse = httpClient.execute(httpPost);
			html = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			httpPost.releaseConnection();

			endT = System.currentTimeMillis();
			showStatus(oddsList, finalDist, 0, true);
			System.out.println("Running time: " + (endT - startT) / 1000 + "s");
			System.out.println("Current ID: " + gambleId);
			System.out.println();

			Thread.sleep(timeout * 1000 + 50000);

		}

	}
}
